<?php

/*
	TF2 Gather Bot v0.11.0
	Módulo para PHP-IRC v2.2.1 (www.phpbots.org)
	Creado por Foxtreme (danig.fox@gmail.com)
	para #gather.es @ Quakenet.org
	
	Archivo: ./modules/gather/core.php
*/

require_once('./modules/gather/config.php');
require_once('./modules/gather/gather.php');
require_once('./modules/gather/lang.es.php');
require_once('./modules/gather/teams.php');
require_once('./modules/gather/topic.php');

class core extends module {
	
	// Variables para definir el módulo
	public $title = 'TF2 Gather Bot *es';
	public $author = 'Foxtreme';
	public $version = '0.11.0 alpha';
	public $version_time = '04/10/09';
	
	// Variables que contendrán objetos
	var $config; // Configuración local del bot 
	var $gather; // Controlador de jugadores
	var $lang; // Cadenas de texto del bot
	var $teams; // Generador de Equipos
	var $topic; // Controlador del Topic
	
	// Variables que almacenarán datos de la BD
	var $banlist; // Lista de baneados
	var $current; // Gather actual
	var $games; // Todos los gathers jugados
	var $noauth; // Usuarios en el canal sin auth
	var $maps; // Mapas votables
	var $options; // Opciones del gather
	var $players; // Todos los usuarios autheados
	var $servers; // Datos de servidores
	var $votes; // Votos de mapas
	var $warnings; // Lista de warnings
	
	// Esta variable indica en que estado está el bot
	// INIT = Iniciándose
	// ON = Activo y aceptando comandos
	// OFF = Activo, no acepta comandos (solo !on)
	// FULL = Hay un gather lleno, a la espera de hacerse equipos
	// STARTED = Ha empezado un gather segundos atrás
	var $bot_status = 'INIT';
	
	// Aquí se almacenan los elementos de la cola de acciones y mensajes
	var $queue = array();
	
	// Cantidad de usuarios en el canal conocidos actualmente
	var $total_users;
	
	// Variables temporales para ejecutar funciones a la espera de datos
	var $q_users = array();
	var	$whois = array();
	
	// Función ejecutada al iniciarse el bot
	public function init() {

		// Seteamos algunas variables necesarias
		$this->q_users['receiving'] = FALSE;
		$this->q_users['sent'] = FALSE;
		
		// Obtenemos datos de la bd
		$this->banlist = $this->_db_get('banlist');
		$this->games = $this->_db_get('games');
		$this->maps = $this->_db_get('maps');
		$this->options = $this->_db_get('options');
		$this->players = $this->_db_get('players');
		$this->servers = $this->_db_get('servers');
		$this->votes = $this->_db_get('votes');
		$this->warnings = $this->_db_get('warnings');
		
		// Creamos instancias de objetos
		$this->config = new Config($this);
		$this->lang = new Lang($this);
		
		$this->gather = new Gather($this);
		$this->teams = new Teams($this);
		$this->topic = new Topic($this);
		
		// Iniciamos el bucle que comprueba la cola de mensajes y acciones cada segundo.
		$this->queue['start'] = TRUE;
		$this->timerClass->addTimer('queue_checker', $this, '_queue_check', '', 1, TRUE);
	}
	
	// Esta función es llamada cuando se cierra el bot
	public function destroy() {
		// Destruye el proceso del bot
		exit(0);
	}
	
	// Parsea la información recibida del servidor. Esta función se ejecuta
	// cada vez que el servidor envía datos al bot.
	public function _raw($line, $args) {
		
		// Lee la cabecera del paquete de datos recibido.
		switch ($line['cmd']) {
			
			// 001: Conectado a la red (Welcome)
			case '001':
				// El bot se registra y se pone modo +x
				$this->ircClass->privMsg('Q@CServe.quakenet.org', 'AUTH ' . $this->config->auth_user . ' ' . $this->config->auth_pass, TRUE);
				$this->ircClass->sendRaw('MODE ' . $this->ircClass->getNick() . ' +x', TRUE);
				
				// Añadimos los canales a los que el bot va a entrar. Esto hace que el bot intente reentrar cada 60 segundos
				// al canal establecido, aun si es kickeado, volverá.
				$this->ircClass->maintainChannel($this->config->chan);
				$this->ircClass->maintainChannel($this->config->chan_admin);
				
				return;
			break;
			
			// 318: Respuesta de WHOIS (Nick sin AUTH)
			case 318:
				if ($this->whois['do']) {
					$auth = (explode(' ', $line['params']));
					$this->_user_do_whois($this->whois['nick'], $auth[1]);
					$this->whois['do'] = FALSE;
				}
				return;
			break;
			
			// 330: Respuesta de WHOIS (Nick con AUTH)
			case 330:
				if ($this->whois['do']) {
					$this->_user_do_whois($this->whois_nick, '__NOT_AUTHED');
					$this->whois['do'] = FALSE;
				}
				return;
			break;
			
			// JOIN: Un usuario entra a un canal (incluído el propio bot)
			case 'JOIN':
				
				// Si el bot entra al canal de gather
				if ((($line['fromNick'] == $this->ircClass->getNick()) && ($line['to'] == $this->config->chan)) || (($this->config->debug) && ($this->_bot_status() == 'INIT'))) {
					// Si hay conexión con la base de datos pedimos los datos de usuarios
					if ($this->db->isConnected()) {
						$this->topic->_set('Gather Bot *es v' . $this->version . ' (' . $this->version_time . ') ' . $this->lang->bot_starting);
						$this->_bot_get_users_auth($this->config->chan);
					}
					else {
						$this->topic->_set('Gather Bot *es v' . $this->version . ' (' . $this->version_time . ') ' . $this->lang->bot_dberror);
					}
				}
				else {
					//$this->_user_do_whois($line['fromNick']);
					//$this->_bot_get_users_auth($this->config->chan);

					// Añadimos a la cola de acciones una petición para actualizar los usuarios del canal
					$this->_queue_action('get_users', $this->config->chan);
				}
				return;
			break;
			
			// KICK, PART, QUIT
			case 'KICK':
			case 'PART':
			case 'QUIT':
				if ($line['cmd'] == 'KICK') {
					$nick = $line['params'];
				}
				else {
					$nick = $line['fromNick'];
				}
				$auth = $this->_user_get_auth($nick);
				
				if ($auth) {
					// Busca al usuario y pone online = 0
					for($i = 1; $i <= $this->players['qty']; $i++) {
						if ($this->players[$i]['auth'] == $auth) {
							$this->players[$i]['online'] = 0;
							break;
						}
					}
				}
				// Si el usuario no esta autheado...
				else {
					for($i = 1; $i < ($this->noauth['qty']); $i++) {
						if ($this->noauth[$i]['nick'] == $nick) {
							$this->noauth[$i]['online'] = 0;
							break;
						}
					}
				}
				
				// Si estaba addeado lo borra
				if ($this->gather->_player_is_added($auth)) {
					$this->gather->_del($auth);
				}
				
				return;
			break;
			
			// NICK: Un usuario cambia su nick
			case 'NICK':
			
				$old_nick = $line['fromNick'];
				$new_nick = $line['text'];
				
				$auth = $this->_user_get_auth($old_nick);
				
				if ($auth) {
					for($i = 1; $i <= $this->players['qty']; $i++) {
						if ($this->players[$i]['auth'] == $auth) {
							$this->players[$i]['nick'] = $line['text'];
							// Actualizamos la base de datos
							if ($this->db->isConnected()) {
								$query = "UPDATE `gather_players` SET `nick` = '" . $new_nick . "' ' WHERE `id` = " . $i;
								$this->db->query($query);
								echo $this->db->getError();
							}
							break;
						}
					}
				}
				
				// Si el usuario no esta autheado...
				else {
					for($i = 1; $i < ($this->noauth['qty']); $i++) {
						if ($this->noauth[$i]['nick'] == $old_nick) {
							$this->noauth[$i]['nick'] = $new_nick;
							break;
						}
					}
				}
				
				// Si estaba addeado actualiza el nick
				if ($this->gather->_player_is_added($auth)) {
					$this->gather->_update_nick($auth, $old_nick, $new_nick);
				}
				
				return;
			break;
			
			// NOTICE: El bot recibe un mensaje tipo NOTICE
			case 'NOTICE':
				// Comprobamos si es una respuesta de MSG Q USERS
				if ($this->q_users['sent']) {
					if ($line['from'] == 'Q!TheQBot@CServe.quakenet.org') {
						
						$line_clean = trim($line['text']);
						$line_clean = preg_replace('/\s\s+/', ' ', $line_clean);
						echo "\n" . $line_clean . "\n";
						switch ($line_clean) {
							
							// Comienzo de datos
							case 'Nick Username Flags Host':
								$this->q_users['receiving'] = TRUE;
								$this->q_users['a'] = 1;
								$this->q_users['n'] = 1;
								$this->q_users['authed_users'] = array();
								$this->q_users['normal_users'] = array();
							break;
							
							// Fin de datos
							case 'End of list.':
								$this->q_users['receiving'] = FALSE;
								$this->q_users['sent'] = FALSE;
								$this->total_users = ($this->q_users['a'] + $this->q_users['n'] - 2);
								$this->noauth['qty'] = $this->q_users['n'];
								if ($this->_bot_status() == 'INIT') {
									// Ponemos el bot en espera durante 10 segundos, e iniciamos el resto de funciones
									$this->timerClass->addTimer('bot_starter', $this, '_bot_starter', '', 10, FALSE);
								}
							break;
							
							default:
								if ($this->q_users['receiving']) {
									$replace = array('+', '@');
									$line_explode = explode(' ', $line_clean);
									// El usuario no tiene auth...
									if (($args['nargs'] == 2) && (substr($line_explode[1], 0, 1) == '(')) {
										$this->noauth[$this->q_users['n']]['nick'] = str_replace($replace, '', $line_explode[0]);
										$this->noauth[$this->q_users['n']]['nick_clean'] = str_replace($replace, '', $args['cmd']);
										$this->noauth[$this->q_users['n']]['mask'] = substr($args['arg2'], 1, -1);
										$this->noauth[$this->q_users['n']]['online'] = 1;
										$this->noauth[$this->q_users['n']]['last_active'] = time();
										$this->noauth[$this->q_users['n']]['afk'] = 0;
										$this->noauth[$this->q_users['n']]['level'] = 0;
										$this->noauth[$this->q_users['n']]['skill'] = 0;
										$this->noauth[$this->q_users['n']]['class1'] = 0;
										$this->noauth[$this->q_users['n']]['class2'] = 0;
										$this->noauth[$this->q_users['n']]['authed'] = 0;
										$this->q_users['n']++;
									}
									// Comprobamos que no sea Q o el propio bot
									elseif (($line_explode[0] != '@Q') && ($args['arg1'] != $this->config->auth_user)) {
										// El usuario no tiene flags pero si modos
										if (($args['nargs'] == 2) && (substr($line_explode[2], 0, 1) == '(')) {
											$this->q_users['authed_users'][$this->q_users['a']]['nick_clean'] = str_replace($replace, '', $args['cmd']);
											$this->q_users['authed_users'][$this->q_users['a']]['auth'] = $args['arg1'];
											$this->q_users['authed_users'][$this->q_users['a']]['modes'] = '';
											$this->q_users['authed_users'][$this->q_users['a']]['mask'] = substr($args['arg2'], 1, -1);
										}
										// El usuario no tiene flags ni modos
										elseif (($args['nargs'] == 3) && (substr($line_explode[2], 0, 1) == '(')) {
											$this->q_users['authed_users'][$this->q_users['a']]['nick_clean'] = $this->ircClass->myStrToLower($args['arg1']);
											$this->q_users['authed_users'][$this->q_users['a']]['auth'] = $args['arg2'];
											$this->q_users['authed_users'][$this->q_users['a']]['modes'] = '';
											$this->q_users['authed_users'][$this->q_users['a']]['mask'] = substr($args['arg3'], 1, -1);
										}
										// User normal (nick, auth, flags, mask)
										else {
											$this->q_users['authed_users'][$this->q_users['a']]['nick_clean'] = str_replace($replace, '', $args['cmd']);
											$this->q_users['authed_users'][$this->q_users['a']]['auth'] = $args['arg1'];
											$this->q_users['authed_users'][$this->q_users['a']]['modes'] = $args['arg2'];
											$this->q_users['authed_users'][$this->q_users['a']]['mask'] = substr($args['arg3'], 1, -1);
										}
										// Nick del usuario
										$this->q_users['authed_users'][$this->q_users['a']]['nick'] = str_replace($replace, '', $line_explode[0]);
										
										// Buscamos el usuario en la base de datos
										$found = FALSE;
										for($i = 1; $i <= $this->players['qty']; $i++) {
											if ($this->players[$i]['auth'] == $this->q_users['authed_users'][$this->q_users['a']]['auth']) {
												// Lo encontramos...
												$player_id = $i;
												$stop = TRUE;
												$found = TRUE;
											}
										}
										if (!$found) {
											// No lo encontramos, creamos un registro nuevo
											$player_id = ($this->players['qty'] + 1);
											echo "\nID: $player_id \n";
											$this->players[$player_id]['auth'] = $this->q_users['authed_users'][$this->q_users['a']]['auth'];
											$this->players['qty']++;
										}
										
										// Seteamos los datos del jugador en el array global
										$this->players[$player_id]['nick'] = $this->q_users['authed_users'][$this->q_users['a']]['nick'];
										$this->players[$player_id]['nick_clean'] = $this->q_users['authed_users'][$this->q_users['a']]['nick_clean'];
										$this->players[$player_id]['mask'] = $this->q_users['authed_users'][$this->q_users['a']]['mask'];
										$this->players[$player_id]['modes'] = $this->q_users['authed_users'][$this->q_users['a']]['modes'];
										$this->players[$player_id]['last_active'] = time();
										$this->players[$player_id]['afk'] = 0;
										$this->players[$player_id]['online'] = 1;
										if ($found) {
											if ($this->db->isConnected()) {
												$query = "UPDATE `gather_players` SET `auth` = '" . $this->players[$player_id]['auth'] . "', `nick` = '" . $this->players[$player_id]['nick'] . "', `nick_clean` = '" . $this->players[$player_id]['nick_clean'] . "', `mask` = '" . $this->players[$player_id]['mask'] . "' WHERE `id` = " . $player_id;
												$this->db->query($query);
												echo $this->db->getError();
											}
										}
										else {
											$fields = array('id', 'auth', 'nick', 'nick_clean', 'mask', 'level', 'skill', 'class1', 'class2', 'no_hl');
											$values = array($player_id, $this->players[$player_id]['auth'], $this->players[$player_id]['nick'], $this->players[$player_id]['nick_clean'], $this->players[$player_id]['mask'], 2, 0, 0, 0, 0);
											$this->_db_insert('players', $fields, $values);
											// Seteamos algunos valores no definidos por la base de datos.
											$this->players[$player_id]['level'] = 2;
											$this->players[$player_id]['skill'] = 0;
											$this->players[$player_id]['class1'] = 0;
											$this->players[$player_id]['class2'] = 0;
											$this->players[$player_id]['no_hl'] = 0;
										}
										
										$this->q_users['a']++;
									}
								}
							break;
						}
					}
				}
			break;
			
			// Si los datos no nos interesan terminamos la ejecución con un return
			default:
				return;
			break;
		}
	}
	
	// Controla los comandos que se usan en el canal y llama a las funciones correspondientes.
	public function _command($line, $args) {
		
		// Si es posible obtenemos el AUTH del usuario que usó el comando
		$nick = $line['fromNick'];
		$nick_auth = $this->_user_get_auth($line['fromNick']);
		
		// Si el comando no se usa en el canal, no funcionará
		if (($line['to'] != $this->config->chan) && ($line['to'] != $this->config->chan_admin)) {
			return;
		}
		
		// Comando !test (debug)
		if ($args['cmd'] == '.!loadtest') {
			if ($this->config->debug) {
				$this->_queue_msg('Cargando, espera...', $this->config->chan);
				$this->_bot_get_users_auth('#gather.es');
			}
			return;
		}
		
		// Comando !level (debug)
		if ($args['cmd'] == '.!level') {
			$this->_queue_msg('Tienes nivel ' . $this->_user_get_level($nick), $this->config->chan);
			return;
		}
		
		// Comando !info (debug)
		if ($args['cmd'] == '.!info') {
			$user_id = FALSE;
			for($i = 1; $i <= $this->players['qty']; $i++) {
				if ($this->players[$i]['nick_clean'] == $this->ircClass->myStrToLower($args['arg1'])) {
					$user_id = $i;
				}
			}
			if ($user_id) {
				$this->ircClass->privMsg($line['to'], 'Info del usuario ' . $args['arg1'] . '->  AUTH: ' . $this->players[$user_id]['auth'] . ', MASK: ' . $this->players[$user_id]['mask'] . ', LEVEL: ' . $this->players[$user_id]['level'] . ', SKILL: ' . $this->players[$user_id]['skill'] . ', CLASE 1: ' . $this->players[$user_id]['class1'] . ', CLASE 2: ' . $this->players[$user_id]['class2']);
			}
			else {
				$this->ircClass->privMsg($line['to'], 'No he encontrado al usuario ' . $args['arg1'] . ' en la base de datos.');
			}
			return;
		}
		
		
		// Comando !quit (Admin 8+)
		// Desconecta el bot de la red y cierra el proceso
		if ($args['cmd'] == '.!quit') {
			if ($this->_user_get_level($nick) > 7) {
				$this->topic->_set('Bot desactivado.');
				$this->ircClass->sendRaw('QUIT :Gather Bot *es v' . $this->version . ' By Foxtreme', TRUE);
				$this->destroy();
			}
			else {
				return;
			}
		}
		
		// Si el bot aún no terminó de cargarse no acepta ningún comando
		if ($this->_bot_status() == 'INIT') {
			return;
		}

		// Si el gather está off solo acepta !on (Admin 7+)
		if ($this->_bot_status() == 'OFF') {
			if (($args['cmd'] == '.!on') && ($this->_user_get_level($nick) > 6)) {
				$this->topic->set('Gather Bot *es v' . $this->version . ' (' . $this->version_time . ') ' . $this->lang->bot_starting);
				$this->_bot_status('ON');
			}
			else {
				$this->_queue_msg($this->lang->bot_off, $line['to']);
			}
			return;
		}

		// Idem si el bot está haciendo equipos...
		if ($this->_bot_status() == 'STARTED') {
			$this->_queue_msg($this->lang->gather_started, $line['to']);
			return;
		}
		
		switch ($args['cmd']) {

		
			// Comando !add
			// Añade al jugador al gather
			case '.!add':
			case '.!addme':
				if ($this->_bot_status() == 'ON') {
					// Comprobamos el nivel del usuario
					switch ($this->_user_get_level($nick)) {
						case 0: // Sin AUTH
							$this->_queue_msg($nick . ': ' . $this->lang->add_no_auth, $line['to']);
						break;
						case 1: // Baneado
							$this->_queue_msg($nick . ': ' . $this->lang->add_banned, $line['to']);
						break;
						case 2: // Con auth, sin aprobar
							$this->_queue_msg($nick . ': ' . $this->lang->add_no_aproval, $line['to']);
						break;
						default:
							// Para level 3 o mayor:
							if (($this->_user_get_level($nick)) >= 3) {
								// !add cuando esta activo el modo de médicos
								if ($this->gather->_get_mode() == 'MEDICS') {
									if ($this->gather->_get_free_slots('normal') > 0) { // Hay hueco
										$this->gather->_add($nick);
									}
									elseif ($this->gather->_get_free_slots('medic') > 0) { // No hay hueco normal pero si de medic
										$this->_queue_msg($this->lang->add_only_medic, $line['to']);
									}
								}
							}
						break;
					}
				}
			break;
			
			
			// Comando !addm
			// Permite a un admin añadir a otro usuario como medic
			case '.!addm':
			case '.!addmedic':
				if ($this->_bot_status() == 'ON') {
					if ($this->_user_get_level($nick) >= 7) {
						// !add cuando esta activo el modo de médicos
						if ($this->gather->_get_mode() == 'MEDICS') {
							if ($this->gather->_get_free_slots('medic') > 0) { // Hay hueco
								for($i = 1; $i <= $args['nargs']; $i++) {
									$this->gather->_add($nick, $args['arg' . $i], TRUE);
								}
							}
							elseif ($this->gather->_get_free_slots('medic') == 0) { // No hay hueco
								$this->_queue_msg($this->lang->addmedic_no_slots, $line['to']);
							}
						}
					}
				}
			break;
			
			
			// Comando !addu
			// Permite a un admin añadir a otro usuario del canal al gather
			case '.!addu':
			case '.!adduser':
				if ($this->_bot_status() == 'ON') {
					if (($this->_user_get_level($nick)) >= 7) {
						// !add cuando esta activo el modo de médicos
						if ($this->gather->_get_mode() == 'MEDICS') {
							if ($this->gather->_get_free_slots('normal') > 0) { // Hay hueco
								for($i = 1; $i <= $args['nargs']; $i++) {
									$this->gather->_add($nick, $args['arg' . $i]);
								}
							}
							elseif ($this->gather->_get_free_slots('medic') > 0) { // No hay hueco normal pero si de medic
								$this->_queue_msg($this->lang->adduser_only_medic, $line['to']);
							}
						}
					}
				}
			break;
			
			
			// Comando !commands
			// Muestra los comandos disponibles
			case '.!commands':
			case '.!comandos':
				$msg = '2,0' . $this->lang->commands_help;
				$msg2 = '2,0' . $this->lang->commands_list;
				$this->_queue_msg($msg, $line['to']);
				$this->_queue_msg($msg2, $line['to']);
				
				if ($this->_user_get_level($nick) >= 7) {
					$msg3 = '2,0' . $nick . ': ' . $this->lang->commands_admin;
					$this->_queue_msg($msg3, $this->config->chan_admin);
				}
			break;
		
		
			// Comando !del
			// Borra a un jugador. También sirve para borrar a otros jugadores (como admin)
			case '.!del':
			case '.!remove':
				if ($this->_bot_status() == 'ON') {
					if (($this->_user_get_level($nick)) >= 3) {
						for($i = 1; $i <= $args['nargs']; $i++) {
							$this->gather->_del($args['arg' . $i]);
						}
					}
					else {
						$this->gather->_del($nick);
					}
				}
			break;
			
			
			// Comando !help
			// Muestra ayuda de gather para nubs!
			case '.!help':
			case '.!ayuda':
			case '.!info':
				$msg = '2,0' . $this->lang->help_1;
				$msg2 =  '2,0' . $this->lang->help_2;
				$this->_queue_msg($msg, $line['to']);
				$this->_queue_msg($msg2, $line['to']);
			break;
			
			
			// Comando !maplist
			// Muestra la lista de mapas votables
			case '.!maplist':
			case '.!lista':
			case '.!mapas':
				$this->_queue_msg('2,0' . $this->lang->maplist . ' ' . $this->gather->_get_maplist(), $line['to']);
			break;
			
			
			// Comando !rules
			// Muestra las normas de gather
			case '.!rules':
			case '.!normas':
				$msg = '2,0' . $this->lang->rules;
				$this->_queue_msg($msg, $line['to']);
			break;
			
			// Comando !status
			// Muestra información del gather actual
			case '.!status':
			case '.!estado':
			case '.!equipos':
			case '.!teams':
				$this->topic->_command_status = TRUE;
			break;
		
			// Comando !votemap
			// Permite a los jugadores votar un mapa
			case '.!votemap':
			case '.!m':
			case '.!map':
			case '.!mapa':
			case '.!v':
			case '.!votar':
			case '.!vote':
				if ($this->gather->_player_is_added($nick)) {
					if ($args['nargs'] >= 1) {
						if ($nick_auth) {
							$this->gather->_votemap($nick, $args['arg1']);
						}
					}
					else {
						$this->_queue_msg('2,0' . $this->lang->votemap_error . ' ' . $this->gather->_get_maplist(), $line['to']);
					}
				}
			break;
		
			//Comando !highlight
		
			// Comando !test (debug)
			/*case '!test':
				if ($this->config->debug) {
					$this->ircClass->privMsg($this->config->chan, 'Cargando, espera...');
					$this->_get_users_auth('#gather.es');
				}
			break;*/
			
					
			// Comando !check (debug)
			case '.!check':
				if ($this->config->debug) {
					print_r($this->queue);
				}
			break;

		}
	}

	
	// Función que inicia los bucles del bot. Es llamada al terminar el proceso completo de $this->_bot_get_users_auth($chan);
	function _bot_starter($arguments) {
		
		if ($this->_bot_status() == 'INIT') {
			
			// Iniciamos el bucle que comprueba el topic cada 4 segundos y lo actualiza si es necesario.
			$this->timerClass->addTimer('topic_checker', $this->topic, '_check', '', 4, TRUE);
			
			// Ponemos modo ON
			$this->_bot_status('ON');
		}
		
		// Devolviendo FALSE impedimos que esta función se ejecute más de una vez.
		return FALSE;
	}
	
	// Comprueba el estado del bot/gather y lo cambia si se envía un parámetro
	public function _bot_status($set = FALSE) {
		if ($set) {
			$this->bot_status = $set;
			return TRUE;
		}
		else {
			return $this->bot_status;
		}
	}

	// Inicia petición de datos de auth de los usuarios de un canal
	public function _bot_get_users_auth($chan) {
		$this->q_users['sent'] = TRUE;
		$this->ircClass->privMsg('Q', 'USERS ' . $chan);
		return TRUE;
	}
	
	// Obtiene datos de la BD
	public function _db_get($table, $field = FALSE, $value = FALSE) {
		
		$return = FALSE;
		// Comprobamos si hay conexión
		if ($this->db->isConnected()) {
			if ($field && $value) { // Si se pide una campo concreto:
				$query = $this->db->query("SELECT * FROM `gather_$table` WHERE `$field`=$value");
				$return = $this->db->fetchArray($query);
				return $return;
			}
			else { // Si no se pide obtenemos todos los datos de la tabla
				$query = $this->db->query("SELECT * FROM `gather_$table`");
				if ($table == 'options') {
					while ($row = $this->db->fetchArray($query)) {
						$return[$row['option']] = $row['value'];
					}
				}
				else {
					while ($row = $this->db->fetchArray($query)) {
						foreach ($row as $key => $value) {
							$return[$row['id']][$key] = $value;
						}
					}
					$return['qty'] = mysql_num_rows($query);
				}
			}
		}
		
		// Retornamos los datos (o un FALSE si no habia conexión con la bd)
		return $return;
	}
	
	// Escribe nuevos datos a la bd
	public function _db_insert($table, $fields, $values, $array = TRUE) {
	
		// Comprobamos si hay conexión
		if ($this->db->isConnected()) {
			if ($array) {
				$query_fields = '';
				$query_values = '';
				foreach ($fields as $f) {
					if ($query_fields == '') {
						$query_fields .= '`' . mysql_real_escape_string($f) . '`';
					}
					else {
						$query_fields .= ', `' . mysql_real_escape_string($f) . '`';
					}
				}
				foreach ($values as $v) {
					if ($query_values == '') {
						$query_values .= "'" . mysql_real_escape_string($v) . "'";
					}
					else {
						$query_values .= ", '" . mysql_real_escape_string($v) . "'";
					}
				}
				$query = "INSERT INTO `gather_$table` ($query_fields) VALUES ($query_values)";
				$this->db->query($query);
			}
			else {
				addslashes($fields);
				addslashes($values);
				$query = $this->db->query("INSERT INTO `gather_$table` (`$fields`) VALUES ('$values')");
			}
			return TRUE;
		}
		else {
			return FALSE;
		}
	}
	
	// Actualiza datos de la BD
	public function _db_update($table, $field, $value, $id = FALSE) {
	
		// Comprobamos si hay conexión
		if ($this->db->isConnected()) {
			if ($table == 'options') {
				$query = $this->db->query("UPDATE `gather_options` SET `value` = '$value' WHERE `option` = '$field'");
			}
			else {
				$query = $this->db->query("UPDATE `gather_$table` SET `$field` = '$value' WHERE `id` = '$id'");
			}
			return TRUE;
		}
		else {
			return FALSE;
		}
	}
	
	// Comprueba y ejecuta acciones de la cola
	// Esta función se ejecuta cada segundo, se inicia mediante un temporizador al iniciar el bot
	public function _queue_check($arguments) {
		// Primera iteración de la cola
		if ($this->queue['start']) {
			$this->queue['last_action'] = 0;
			$this->queue['item_total'] = 1;
			$this->queue['next_empty_item'] = 1;
			$this->queue['item'][1]['action'] = '';
			$this->queue['item'][1]['chan'] = '';
			$this->queue['item'][1]['msg'] = '';
			$this->queue['item'][1]['empty'] = TRUE;
			$this->queue['start'] = FALSE;
		}
		
		// Si han pasado menos de 2 segundos desde la última acción no se ejecuta el bucle.
		if ((time()) < ($this->queue['last_action'] + 2)) {
			return TRUE;
		}
		
		for ($i = 1; $i <= $this->queue['item_total']; $i++) {
			if ($this->queue['item'][$i]['empty'] == FALSE) {
				switch ($this->queue['item'][$i]['action']) {
					case 'get_users':
						$this->_bot_get_users_auth($this->queue['item'][$i]['chan']);
					break;
					
					case 'msg':
						$this->ircClass->privMsg($this->queue['item'][$i]['chan'], $this->queue['item'][$i]['msg']);
					break;
				}
				
				$this->queue['item'][$i]['empty'] = TRUE;
				$this->queue['last_action'] = time();
				break;
			}
		}
		
		return TRUE;
	}
	
	// Añade una acción a la cola
	public function _queue_add($action, $chan) {
	
		$all_used = TRUE;
		for ($i = 1; $i <= $this->queue['item_total']; $i++) {
			if ($this->queue['item'][$i]['empty'] == TRUE) {
				$next_empty_item = $i;
				$all_used = FALSE;
				break;
			}
		}
		// Si todos los elementos están en uso añadimos uno vacío.
		if ($all_used) {
			$this->queue['item_total']++;
			$next_empty_item = $this->queue['item_total'];
			$this->queue['item'][$this->queue['item_total']]['action'] = '';
			$this->queue['item'][$this->queue['item_total']]['chan'] = '';
			$this->queue['item'][$this->queue['item_total']]['msg'] = '';
			$this->queue['item'][$this->queue['item_total']]['empty'] = TRUE;
		}
			
		// Comprobamos que no exista en cola un elemento igual
		$new_item = TRUE;
		for ($i = 1; $i <= $this->queue['item_total']; $i++) {
			if (($this->queue['item'][$i]['action'] == $action) && ($this->queue['item'][$i]['chan'] == $chan) && ($this->queue['item'][$i]['empty'] == FALSE)) {
				$new_item = FALSE;
				break;
			}
		}
		if ($new_item) {
			$this->queue['item'][$next_empty_item]['action'] = $action;
			$this->queue['item'][$next_empty_item]['chan'] = $chan;
			$this->queue['item'][$next_empty_item]['empty'] = FALSE;
		}
		return;
	}
	
	// Añade un mensaje a la cola
	public function _queue_msg($msg, $chan) {
		echo "Añadiendo $msg para $chan\n\n";
		print_r($this->queue);
		
		$all_used = TRUE;
		for ($i = 1; $i <= $this->queue['item_total']; $i++) {
			if ($this->queue['item'][$i]['empty'] == TRUE) {
				$next_empty_item = $i;
				$all_used = FALSE;
				break;
			}
		}
		// Si todos los elementos están en uso añadimos uno vacío.
		if ($all_used) {
			$this->queue['item_total']++;
			$next_empty_item = $this->queue['item_total'];
			$this->queue['item'][$this->queue['item_total']]['action'] = '';
			$this->queue['item'][$this->queue['item_total']]['chan'] = '';
			$this->queue['item'][$this->queue['item_total']]['msg'] = '';
			$this->queue['item'][$this->queue['item_total']]['empty'] = TRUE;
		}
		
		// Comprobamos que no exista en cola un mensaje igual
		$new_item = TRUE;
		for ($i = 1; $i <= $this->queue['item_total']; $i++) {
			if (($this->queue['item'][$i]['action'] == 'msg') && ($this->queue['item'][$i]['chan'] == $chan) && ($this->queue['item'][$i]['msg'] == $msg) && ($this->queue['item'][$i]['empty'] == FALSE)) {
				$new_item = FALSE;
				echo "DUPLICADO !!\n\n";
				break;
			}
		}
		if ($new_item) {
			$this->queue['item'][$next_empty_item]['action'] = 'msg';
			$this->queue['item'][$next_empty_item]['chan'] = $chan;
			$this->queue['item'][$next_empty_item]['msg'] = $msg;
			$this->queue['item'][$next_empty_item]['empty'] = FALSE;
			echo "Añadido! en " . $next_empty_item . "- $msg para $chan\n\n";
		}
		else {
			echo "WTF!! \n\n";
		}
		return;
	}
	
	// Busca el siguiente item vacío de la cola
	public function _queue_search_empty() {
		$all_used = TRUE;
		for ($i = 1; $i <= $this->queue['item_total']; $i++) {
			if ($this->queue['item'][$i]['empty'] == TRUE) {
				$this->queue['next_empty_item'] = $i;
				$all_used = FALSE;
				break;
			}
		}
		// Si todos los elementos están en uso añadimos uno vacío.
		if ($all_used) {
			$this->queue['item_total']++;
			$this->queue['next_empty_item'] = $this->queue['item_total'];
			$this->queue['item'][$this->queue['item_total']]['action'] = '';
			$this->queue['item'][$this->queue['item_total']]['chan'] = '';
			$this->queue['item'][$this->queue['item_total']]['msg'] = '';
			$this->queue['item'][$this->queue['item_total']]['empty'] = TRUE;
		}
	}
	
	// Hace un WHOIS a un nick y obtiene el AUTH
	public function _user_do_whois($nick, $auth = FALSE) {
		
		$this->last_whois = time();
		
		if (!($auth)) {
			$this->whois['do'] = TRUE;
			$this->whois['nick'] = $nick;
			$this->ircClass->sendRaw('WHOIS ' . $nick);
		}
		
		// Esta parte se ejecuta tras recibir los datos de WHOIS del servidor		
		// Sin AUTH
		elseif ($auth == '__NOT_AUTHED') {
			//$user = $this->ircClass->getUserData($nick, $this->config['canal_gather']);
			$this->noauth[$this->q_users['n']]['nick'] = str_replace($replace, '', $line_explode[0]);
			$this->noauth[$this->q_users['n']]['nick_clean'] = str_replace($replace, '', $args['cmd']);
			$this->noauth[$this->q_users['n']]['mask'] = substr($args['arg2'], 1, -1);
			$this->noauth[$this->q_users['n']]['online'] = 1;
			$this->noauth[$this->q_users['n']]['last_active'] = time();
			$this->noauth[$this->q_users['n']]['afk'] = 0;
			$this->noauth[$this->q_users['n']]['level'] = 0;
			$this->noauth[$this->q_users['n']]['skill'] = 0;
			$this->noauth[$this->q_users['n']]['class1'] = 0;
			$this->noauth[$this->q_users['n']]['class2'] = 0;
			$this->noauth[$this->q_users['n']]['authed'] = 0;
			$this->noauth['qty']++;
			$this->total_users++;
		}
		// Usuario con AUTH
		else {
			$this->total_users++;
		}
	}
	
	// Obtiene el auth de un nick
	public function _user_get_auth($nick) {
		
		// Buscamos al usuario
		// Usuario sin AUTH
		for($i = 1; $i < ($this->noauth['qty']); $i++) {
			if ($this->noauth[$i]['nick'] == $nick) {
				return FALSE;
			}
		}
		// Usuario con AUTH
		for($i = 1; $i < ($this->players['qty']); $i++) {
			if ($this->players[$i]['nick'] == $nick) {
				return $this->players[$i]['auth'];
			}
		}
	}
	
	// Comprueba el nivel de permisos de un usuario
	public function _user_get_level($nick) {
		
		// Permisos:
		// 0 - Sin auth
		// 1 - Con auth, baneado
		// 2 - Con auth
		// 3 - Con auth, aprobado
		// 7 - Admin normal
		// 8 - Full Admin
		// 9 - Full Admin (bot)
		// 10 - Full Admin (debug)
		
		// Debug
		if ($this->config->debug) {
			return 10;
		}
		
		$auth = $this->_user_get_auth($nick);
		if ($auth) {
			for($i = 1; $i < ($this->players['qty']); $i++) {
				if ($this->players[$i]['auth'] == $auth) {
					return $this->players[$i]['level'];
				}
			}
		}
		// El nick no tiene auth (level 0)
		else {
			return 0;
		}
	}
	
}

?>